/**************************************************************************** 
 * Meta，一个轻量级的静态分区Hypervisor 
 *
 * 版权(c) , 2022-
 *
 * 作者:
 *      Tupelo Shen <shenwanjiang2013@163.com>
 *
 * Meta是一个自由软件，你可以在遵循GNU GPLv2协议的条件下，重新修改并发布它。
 *
 ***************************************************************************/

#include <arch/gic.h>
#include <platform.h>
#include <cpu.h>
#include <mem.h>
#include <fences.h>

/****************************************************************************
 ****                           变量声明                                 ****
 ****************************************************************************/
extern  volatile struct gicd_hw     gicd;
        volatile struct gicr_hw     *gicr;

static spinlock_t   gicd_lock;
static spinlock_t   gicr_lock;

/* 列表寄存器的数量 */
size_t g_num_lrs;

/****************************************************************************
 ****                           私有函数接口                             ****
 ****************************************************************************/
static inline void gicr_init(void);
static inline void gicc_init(void);

/****************************************************************************
 ****                           公共函数定义                             ****
 ****************************************************************************/
/**
 * 功能描述: 将gicd和gicr寄存器的虚拟地址和物理地址建立映射(IO内存映射)
 *           gicd使用全局变量，位于自定义的`.devices`段
 *           gicr是CPU核私有的，动态申请内存（位于hypervisor的全局地址空间）
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_map_mmio()
{
    mem_map_dev(&cpu.as, (vaddr_t)&gicd, platform.arch.gic.gicd_addr,
                NUM_PAGES(sizeof(gicd)));
    size_t gicr_size = NUM_PAGES(sizeof(struct gicr_hw)) * platform.cpu_num;
    gicr = (struct gicr_hw *)mem_alloc_vpage(&cpu.as,
                                             SEC_HYP_GLOBAL,
                                             NULL_VA,
                                             gicr_size);
    mem_map_dev(&cpu.as, (vaddr_t)gicr, platform.arch.gic.gicr_addr, gicr_size);
}

/**
 * 功能描述: 初始化CPU interface
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_cpu_init(void)
{
    gicr_init();
    gicc_init();
}

/**
 * 功能描述: 返回维护中断状态信息寄存器（ICH_MISR_EL2）的值
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: uint32_t 返回寄存器的低32位（该寄存器的位[63-8]保留RES0）
 * 修改日期: 2022-09-21
 */
uint32_t gich_get_misr()
{
    return MRS(ICH_MISR_EL2);
}

/**
 * 功能描述: 返回中断结束状态寄存器（ICH_EISR_EL2）的值
 *           该寄存器的值表明列表寄存器中的挂起中断已经处理完毕，但是还没有清理
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: uint64_t 返回寄存器的值
 * 修改日期: 2022-09-21
 */
uint64_t gich_get_eisr()
{
    return MRS(ICH_EISR_EL2);
}

/**
 * 功能描述: 返回中断虚拟化控制寄存器（ICH_HCR_EL2）的值
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: uint32_t: 返回寄存器的值（该寄存器的高32位保留，所以只需低32位）
 * 修改日期: 2022-09-21
 */
uint32_t gich_get_hcr()
{
    return MRS(ICH_HCR_EL2);
}

/**
 * 功能描述: 设置中断虚拟化控制寄存器（ICH_HCR_EL2）的值
 * 入口参数: hcr,   要设置的值（该寄存器的高32位保留，所以只需设置低32位）
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gich_set_hcr(uint32_t hcr)
{
    MSR(ICH_HCR_EL2, hcr);
}

/**
 * 功能描述: 返回空列表寄存器状态寄存器（ELRSR）的值
 *           该寄存器的值表明列表寄存器中的挂起中断已经处理完毕，但是还没有清理
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: uint64_t 返回寄存器的值
 * 修改日期: 2022-09-21
 */
uint64_t gich_get_elrsr()
{
    return MRS(ICH_ELRSR_EL2);
}
/**
 * 功能描述: 返回i索引的列表寄存器
 * 入口参数: i, 列表寄存器的索引
 * 出口参数: void
 * 返 回 值: uint64_t 返回寄存器的值
 * 修改日期: 2022-09-21
 */
inline unsigned long gich_read_lr(size_t i)
{
    if (i >= g_num_lrs) {
        ERROR("gic: trying to read inexistent list register");
    }

    switch (i) {
        case 0: return MRS(ICH_LR0_EL2);
        case 1: return MRS(ICH_LR1_EL2);
        case 2: return MRS(ICH_LR2_EL2);
        case 3: return MRS(ICH_LR3_EL2);
        case 4: return MRS(ICH_LR4_EL2);
        case 5: return MRS(ICH_LR5_EL2);
        case 6: return MRS(ICH_LR6_EL2);
        case 7: return MRS(ICH_LR7_EL2);
        case 8: return MRS(ICH_LR8_EL2);
        case 9: return MRS(ICH_LR9_EL2);
        case 10: return MRS(ICH_LR10_EL2);
        case 11: return MRS(ICH_LR11_EL2);
        case 12: return MRS(ICH_LR12_EL2);
        case 13: return MRS(ICH_LR13_EL2);
        case 14: return MRS(ICH_LR14_EL2);
        case 15: return MRS(ICH_LR15_EL2);
        default: return 0;
    }
}

/**
 * 功能描述: 返回i索引的列表寄存器
 * 入口参数: i:     列表寄存器的索引
 *           val:   写入列表寄存器的值
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
inline void gich_write_lr(size_t i, unsigned long val)
{
    if (i >= g_num_lrs) {
        ERROR("gic: trying to write inexistent list register");
    }

    switch (i) {
        case 0: MSR(ICH_LR0_EL2, val);   break;        
        case 1: MSR(ICH_LR1_EL2, val);   break;         
        case 2: MSR(ICH_LR2_EL2, val);   break;         
        case 3: MSR(ICH_LR3_EL2, val);   break;         
        case 4: MSR(ICH_LR4_EL2, val);   break;         
        case 5: MSR(ICH_LR5_EL2, val);   break;         
        case 6: MSR(ICH_LR6_EL2, val);   break;         
        case 7: MSR(ICH_LR7_EL2, val);   break;         
        case 8: MSR(ICH_LR8_EL2, val);   break;         
        case 9: MSR(ICH_LR9_EL2, val);   break;         
        case 10: MSR(ICH_LR10_EL2, val); break;           
        case 11: MSR(ICH_LR11_EL2, val); break;           
        case 12: MSR(ICH_LR12_EL2, val); break;           
        case 13: MSR(ICH_LR13_EL2, val); break;           
        case 14: MSR(ICH_LR14_EL2, val); break;           
        case 15: MSR(ICH_LR15_EL2, val); break;
    }
}

/**
 * 功能描述: 获取gic控制器中的列表寄存器数量
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: uint64_t: 列表寄存器数量
 * 修改日期: 2022-09-21
 */
size_t gich_num_lrs(void)
{
    return ((MRS(ICH_VTR_EL2) & ICH_VTR_MSK) >> ICH_VTR_OFF) + 1;
}

/**
 * 功能描述: 设置pending状态
 * 入口参数: int_id:    中断ID
 *           pend:      是否挂起(bool)
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_set_pend(irqid_t int_id, bool pend)
{
    if (!gic_is_priv(int_id)) {
        gicd_set_pend(int_id, pend);
    } else {
        gicr_set_pend(int_id, pend, cpu.id);
    }
}

/**
 * 功能描述: 获取pending状态
 * 入口参数: int_id:    中断ID
 * 出口参数: void
 * 返 回 值: bool:      返回挂起状态
 * 修改日期: 2022-09-21
 */
bool gic_get_pend(irqid_t int_id)
{
    if (!gic_is_priv(int_id)) {
        return gicd_get_pend(int_id);
    } else {
        return gicr_get_pend(int_id, cpu.id);
    }
}

/**
 * 功能描述: 设置act状态
 * 入口参数: int_id:    中断ID
 *           act:       中断信号是否active？
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_set_act(irqid_t int_id, bool act)
{
    if (!gic_is_priv(int_id)) {
        gicd_set_act(int_id, act);
    } else {
        gicr_set_act(int_id, act, cpu.id);
    }
}
bool gic_get_act(irqid_t int_id)
{
    if (!gic_is_priv(int_id)) {
        return gicd_get_act(int_id);
    } else {
        return gicr_get_act(int_id, cpu.id);
    }
}

/**
 * 功能描述: 设置Redistributor中断pending状态
 * 入口参数: int_id:    中断ID
 *           pend:      中断pending状态
 *           gicr_id:   redistributor编号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicr_set_pend(irqid_t int_id, bool pend, cpuid_t gicr_id)
{
    spin_lock(&gicr_lock);
    if (pend) {
        gicr[gicr_id].ISPENDR0 = (1U) << (int_id);
    } else {
        gicr[gicr_id].ICPENDR0 = (1U) << (int_id);
    }
    spin_unlock(&gicr_lock);
}

/**
 * 功能描述: 获取Redistributor中断pending状态
 * 入口参数: int_id:    中断ID
 *           gicr_id:   redistributor编号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
bool gicr_get_pend(irqid_t int_id, cpuid_t gicr_id)
{
    if (gic_is_priv(int_id)) {
        return !!(gicr[gicr_id].ISPENDR0 & GIC_INT_MASK(int_id));
    } else {
        return false;
    }
}

/**
 * 功能描述: 设置Redistributor中断active状态
 * 入口参数: int_id:    中断ID
 *           act:       中断active状态
 *           gicr_id:   redistributor编号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicr_set_act(irqid_t int_id, bool act, cpuid_t gicr_id)
{
    spin_lock(&gicr_lock);

    if (act) {
        gicr[gicr_id].ISACTIVER0 = GIC_INT_MASK(int_id);
    } else {
        gicr[gicr_id].ICACTIVER0 = GIC_INT_MASK(int_id);
    }

    spin_unlock(&gicr_lock);
}

/**
 * 功能描述: 获取Redistributor中断active状态
 * 入口参数: int_id:    中断ID
 *           gicr_id:   redistributor编号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
bool gicr_get_act(irqid_t int_id, cpuid_t gicr_id)
{
    if (gic_is_priv(int_id)) {
        return !!(gicr[gicr_id].ISACTIVER0 & GIC_INT_MASK(int_id));
    } else {
        return false;
    }
}

/**
 * 功能描述: 保存CPU interface寄存器信息
 * 入口参数: state:     要保存的状态
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicc_save_state(struct gicc_state *state)
{
    state->PMR = MRS(ICC_PMR_EL1);
    state->BPR = MRS(ICC_BPR1_EL1);
    state->priv_ISENABLER = gicr[cpu.id].ISENABLER0;

    for (size_t i = 0; i < GIC_NUM_PRIO_REGS(GIC_CPU_PRIV); i++) {
        state->priv_IPRIORITYR[i] = gicr[cpu.id].IPRIORITYR[i];
    }

    state->HCR = MRS(ICH_HCR_EL2);
    for (size_t i = 0; i < gich_num_lrs(); i++) {
        state->LR[i] = gich_read_lr(i);
    }
}

/**
 * 功能描述: 恢复CPU interface寄存器信息
 * 入口参数: state:     要恢复的状态
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicc_restore_state(struct gicc_state *state)
{
    MSR(ICC_SRE_EL2, ICC_SRE_SRE_BIT);
    MSR(ICC_CTLR_EL1, ICC_CTLR_EOIMode_BIT);
    MSR(ICC_IGRPEN1_EL1, ICC_IGRPEN_EL1_ENB_BIT);
    MSR(ICC_PMR_EL1, state->PMR);
    MSR(ICC_BPR1_EL1, state->BPR);
    gicr[cpu.id].ISENABLER0 = state->priv_ISENABLER;

    for (size_t i = 0; i < GIC_NUM_PRIO_REGS(GIC_CPU_PRIV); i++) {
        gicr[cpu.id].IPRIORITYR[i] = state->priv_IPRIORITYR[i];
    }

    MSR(ICH_HCR_EL2, state->HCR);
    for (size_t i = 0; i < gich_num_lrs(); i++) {
        gich_write_lr(i, state->LR[i]);
    }
}

/**
 * 功能描述: 设置gic中断使能位
 *           (1) 共享中断通过`GICD`设置
 *           (2) 私有中断通过`GICR`设置
 * 入口参数: int_id:    中断ID
 *           en:        使能位
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_set_enable(irqid_t int_id, bool en)
{
    if (!gic_is_priv(int_id)) {
        gicd_set_enable(int_id, en);
    } else {
        gicr_set_enable(int_id, en, cpu.id);
    }
}

/**
 * 功能描述: 设置gic中断优先级
 *           (1) 共享中断通过`GICD`设置
 *           (2) 私有中断通过`GICR`设置
 * 入口参数: int_id:    中断ID
 *           prio:      优先级
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_set_prio(irqid_t int_id, uint8_t prio)
{
    if (!gic_is_priv(int_id)) {
        gicd_set_prio(int_id, prio);
    } else {
        gicr_set_prio(int_id, prio, cpu.id);
    }
}
uint8_t gic_get_prio(irqid_t int_id)
{
    if (!gic_is_priv(int_id)) {
        return gicd_get_prio(int_id);
    } else {
        return gicr_get_prio(int_id, cpu.id);
    }
}
/**
 * 功能描述: 产生软件中断
 * 入口参数: target_cpu,目标核
 *           ipi_id,    软中断号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_send_sgi(cpuid_t cpu_target, irqid_t sgi_num)
{
    if (sgi_num < GIC_MAX_SGIS) {
        unsigned long mpidr = cpu_id_to_mpidr(cpu_target) & MPIDR_AFF_MSK;
        /* We only support two affinity levels */
        uint64_t sgi = (MPIDR_AFF_LVL(mpidr, 1) << ICC_SGIR_AFF1_OFFSET) |
                       (1UL << MPIDR_AFF_LVL(mpidr, 0)) |
                       (sgi_num << ICC_SGIR_SGIINTID_OFF);             
        MSR(ICC_SGI1R_EL1, sgi);
    }
}

/**
 * 功能描述: 设置中断配置
 * 入口参数: int_id,    目标核
 *           cfg,       配置
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_set_icfgr(irqid_t int_id, uint8_t cfg)
{
    if (!gic_is_priv(int_id)) {
        gicd_set_icfgr(int_id, cfg);
    } else {
        gicr_set_icfgr(int_id, cfg, cpu.id);
    }
}

/**
 * 功能描述: 设置gicr私有中断使能位
 * 入口参数: int_id:    中断ID
 *           en:        使能位
 *           gicr_id:   gicr对应编号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicr_set_enable(irqid_t int_id, bool en, cpuid_t gicr_id)
{
    uint32_t bit = GIC_INT_MASK(int_id);

    spin_lock(&gicr_lock);
    if (en)
        gicr[gicr_id].ISENABLER0 = bit;
    else
        gicr[gicr_id].ICENABLER0 = bit;
    spin_unlock(&gicr_lock);
}

/**
 * 功能描述: 设置gicr私有中断优先级
 * 入口参数: int_id:    中断ID
 *           prio:      优先级
 *           gicr_id:   gicr对应编号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicr_set_prio(irqid_t int_id, uint8_t prio, cpuid_t gicr_id)
{
    size_t reg_ind = GIC_PRIO_REG(int_id);
    size_t off = GIC_PRIO_OFF(int_id);
    uint32_t mask = BIT32_MASK(off, GIC_PRIO_BITS);

    spin_lock(&gicr_lock);

    gicr[gicr_id].IPRIORITYR[reg_ind] =
        (gicr[gicr_id].IPRIORITYR[reg_ind] & ~mask) | ((prio << off) & mask);

    spin_unlock(&gicr_lock);
}
uint8_t gicr_get_prio(irqid_t int_id, cpuid_t gicr_id)
{
    size_t reg_ind = GIC_PRIO_REG(int_id);
    size_t off = GIC_PRIO_OFF(int_id);

    spin_lock(&gicr_lock);

    uint8_t prio =
        gicr[gicr_id].IPRIORITYR[reg_ind] >> off & BIT32_MASK(off, GIC_PRIO_BITS);

    spin_unlock(&gicr_lock);

    return prio;
}
/**
 * 功能描述: 设置gicr中断配置
 * 入口参数: int_id,    中断ID
 *           cfg,       配置
 *           gicr_id,   gicr寄存器编号，对应cpuid
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicr_set_icfgr(irqid_t int_id, uint8_t cfg, cpuid_t gicr_id)
{
    size_t reg_ind = (int_id * GIC_CONFIG_BITS) / (sizeof(uint32_t) * 8);
    size_t off = (int_id * GIC_CONFIG_BITS) % (sizeof(uint32_t) * 8);
    uint32_t mask = ((1U << GIC_CONFIG_BITS) - 1) << off;

    spin_lock(&gicr_lock);

    if (reg_ind == 0) {
        gicr[gicr_id].ICFGR0 =
            (gicr[gicr_id].ICFGR0 & ~mask) | ((cfg << off) & mask);
    } else {
        gicr[gicr_id].ICFGR1 =
            (gicr[gicr_id].ICFGR1 & ~mask) | ((cfg << off) & mask);
    }

    spin_unlock(&gicr_lock);
}

/**
 * 功能描述: 设置gicd共享中断路由目标
 * 入口参数: int_id:    中断ID
 *           route:     路由目标
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicd_set_route(irqid_t int_id, unsigned long route)
{
    if (gic_is_priv(int_id)) return;

    spin_lock(&gicd_lock);

    gicd.IROUTER[int_id] = route & GICD_IROUTER_AFF_MSK;

    spin_unlock(&gicd_lock);
}

/**
 * 功能描述: 获取gicc_iar中断确认寄存器，中断进入active状态
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: uint32_t,     返回寄存器值
 * 修改日期: 2022-09-21
 */
uint32_t gicc_iar(void)
{
    return MRS(ICC_IAR1_EL1);
}

/**
 * 功能描述: 写gicc_eoir中断结束寄存器
 * 入口参数: eoir,  写入的值
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicc_eoir(uint32_t eoir)
{
    MSR(ICC_EOIR1_EL1, eoir);
}

/**
 * 功能描述: 写gicc_dir中断失效寄存器
 * 入口参数: dir,   写入的值
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gicc_dir(uint32_t dir)
{
    MSR(ICC_DIR_EL1, dir);
}

/****************************************************************************
 ****                       私有函数定义                                 ****
 ****************************************************************************/
/**
 * 功能描述: gicr初始化
 *           每个CPU核对应一个Redistributor
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static inline void gicr_init(void)
{
    gicr[cpu.id].ICENABLER0 = -1;
    gicr[cpu.id].ICPENDR0 = -1;
    gicr[cpu.id].ICACTIVER0 = -1;

    for (size_t i = 0; i < GIC_NUM_PRIO_REGS(GIC_CPU_PRIV); i++) {
        gicr[cpu.id].IPRIORITYR[i] = -1;
    }
}

/**
 * 功能描述: gicc初始化
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static inline void gicc_init(void)
{
    /* 使能系统寄存器接口 */
    MSR(ICC_SRE_EL2, ICC_SRE_SRE_BIT);
    ISB();

    /* 清零列表寄存器 */
    for (size_t i = 0; i < gich_num_lrs(); i++) {
        gich_write_lr(i, 0);
    }

    /* 设置中断优先级掩码寄存器：允许所有中断优先级 */
    MSR(ICC_PMR_EL1, GIC_LOWEST_PRIO);
    /* 设置Binary Point分割点，用于`group`和`subpriority`优先级 */
    MSR(ICC_BPR1_EL1, 0x0);
    /* 设置中断结束模式：将 priority drop 和 interrupt deactivation功能分开 */
    MSR(ICC_CTLR_EL1, ICC_CTLR_EOIMode_BIT);
    /* 使能维护中断（列表寄存器项不存在） */
    MSR(ICH_HCR_EL2, MRS(ICH_HCR_EL2) | ICH_HCR_LRENPIE_BIT);
    /* 使能`Group 1`中断 */
    MSR(ICC_IGRPEN1_EL1, ICC_IGRPEN_EL1_ENB_BIT);
}